package main

import "fmt"

/*
										Go 语言变量
-------------------------------------------------------------------------------------------
1.变量
变量来源于数学，是计算机语言中能储存计算结果或能表示值抽象概念。
变量可以通过变量名访问。
Go 语言变量名由字母、数字、下划线组成，其中首个字符不能为数字。

声明变量的一般形式是使用 var 关键字：
var identifier type

可以一次声明多个变量：
var identifier1, identifier2 type
-------------------------------------------------------------------------------------------
2.变量声明
第一种，指定变量类型，如果没有初始化，则变量默认为零值。（零值就是变量没有做初始化时系统默认设置的值。）
var v_name v_type
v_name = value

第二种，根据值自行判定变量类型。
var v_name = value

第三种，省略 var, 注意 := 左侧如果没有声明新的变量，就产生编译错误，格式：
v_name := value

var intVal int
intVal :=1 // 这时候会产生编译错误
intVal,intVal1 := 1,2 // 此时不会产生编译错误，因为有声明新的变量，因为 := 是一个声明语句
-------------------------------------------------------------------------------------------
3.变量的默认值
数值类型（包括complex64/128）为 0

布尔类型为 false

字符串为 ""（空字符串）

以下几种类型为 nil：
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口

-------------------------------------------------------------------------------------------
4.多变量声明
类型相同多个变量, 非全局变量:
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3

var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型，自动推断

vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的，否则会导致编译错误


这种因式分解关键字的写法一般用于声明全局变量:
var (
    vname1 v_type1
    vname2 v_type2
)

-------------------------------------------------------------------------------------------
5.值类型和引用类型

	所有像 int、float、bool 和 string 这些基本类型都属于值类型，使用这些类型的变量直接指向存在内存中的值,
当使用等号 = 将一个变量的值赋值给另一个变量时，如：j = i，实际上是在内存中将 i 的值进行了拷贝.

	你可以通过 &i 来获取变量 i 的内存地址，例如：0xf840000040（每次的地址都可能不一样）。值类型的变量的值存
储在栈中。内存地址会根据机器的不同而有所不同，甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器
可能有不同的存储器布局，并且位置分配也可能不同。

	更复杂的数据通常会需要使用多个字，这些数据一般使用引用类型保存。一个引用类型的变量 r1 存储的是 r1 的值所在的
内存地址（数字），或内存地址中第一个字所在的位置。

-------------------------------------------------------------------------------------------
6.空白标识符
	空白标识符 _ 也被用于抛弃值，如值 5 在：_, b = 5, 7 中被抛弃。
_ 实际上是一个只写变量，你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量，但有时你并不需要使用从一
个函数得到的所有返回值。
-------------------------------------------------------------------------------------------
7.语言变量作用域
作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。

Go 语言中变量可以在三个地方声明：

函数内定义的变量称为局部变量
函数外定义的变量称为全局变量
函数定义中的变量称为形式参数

-------------------------------------------------------------------------------------------
不同类型的局部和全局变量默认值为：

数据类型				初始化默认值
int					0
float32				0
pointer				nil
*/

/*
形式参数:
形式参数会作为函数的局部变量来使用。实例如下：
*/

/* 函数定义-两数相加 */
func sum7(a, b int) int {
	fmt.Printf("sum7() 函数中 a = %d\n", a)
	fmt.Printf("sum7() 函数中 b = %d\n", b)

	return a + b
}
func test7() {
	var a int = 10
	var b int = 20
	var c int = 0

	fmt.Printf("test7()函数中 a = %d\n", a)
	c = sum7(a, b)
	fmt.Printf("test7()函数中 c = %d\n", c)
}

/*
全局变量:在函数体外声明的变量称之为全局变量，全局变量可以在整个包甚至外部包（被导出后）使用
Go 语言程序中全局变量与局部变量名称可以相同，但是函数内的局部变量会被优先考虑。实例如下：
*/
/* 声明全局变量 */
var g int
var x int = 90

func test6() {
	/* 声明局部变量 */
	var a, b int

	/* 初始化参数 */
	a = 10
	b = 20
	g = a + b
	var x int = 80
	fmt.Printf("结果： a = %d, b = %d and g = %d, x=%d\n", a, b, g, x)
}

/*局部变量:在函数体内声明的变量称之为局部变量，它们的作用域只在函数体内，参数和返回值变量也是局部变量。
 */
func test5() {
	/* 声明局部变量 */
	var a, b, c int

	/* 初始化参数 */
	a = 10
	b = 20
	c = a + b

	fmt.Printf("结果： a = %d, b = %d and c = %d\n", a, b, c)
}

/*
 使用 := 声明符
*/
func test4() {
	var i int
	i, j := 1, 2
	fmt.Println(i, j)
}

/**
根据值自动判定变量类型
*/
func test3() {
	var d = true
	fmt.Println(d)
}

/**
变量声明
*/
func test2() {
	var a string = "hell go"
	fmt.Println(a)

	var b, c int = 1, 2
	fmt.Println(b, c)
}

/**
变量的默认值
*/
func test1() {
	var i int
	var f float64
	var b bool
	var s string
	fmt.Printf("%v %v %v %q\n", i, f, b, s)
}

func main3() {
	//test1()
	//test2()
	//test3()
	//test4()
	//test5()
	//test6()
	test7()
}
